package com.jbxie.spaceiotmqtt.service;

import com.jbxie.spaceiotmqtt.common.DataPackage;
import com.jbxie.spaceiotmqtt.common.Node;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import top.ninwoo.bishe.starter.service.NetworkService;
import top.ninwoo.common.entity.DockerContainer;

import javax.xml.crypto.Data;
import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.ArrayList;
import java.util.List;

public class NodeService {
    private static final Logger logger = LoggerFactory.getLogger(NodeService.class);

    @Autowired
    DockerContainer dockerContainer;

    @Autowired
    IPService ipService;

    /**
     * 获取当前节点名
     * (需要重写)
     */
    public String getName() {
        return dockerContainer.getName();
    }

    /**
     * 当前节点接收到数据包进行处理
     * 先写一个单向的
     * @param dataPackage
     */
    private void accept(DataPackage dataPackage) {
        String currentName = getName();
        int currentHop = getCurrentHop(currentName);
        Node node = new Node(currentName);
        ServerSocket serverSocket = null;
        InputStream inputStream = null;
        ObjectInputStream objectInputStream = null;
        try {
            serverSocket = new ServerSocket(2021);
            while (true) {
                Socket client = serverSocket.accept();
                inputStream = client.getInputStream();
                objectInputStream = new ObjectInputStream(new BufferedInputStream(inputStream));
                Object object = objectInputStream.readObject();
                DataPackage dataPackage1 = (DataPackage) object;

                List<String> businessList = node.getBusinessList();
                String businessName = dataPackage.getBusinessName();
                ArrayList<String> route = dataPackage.getRoute();
                route.add("sate" + currentHop);
                // 如果计数器仍然等于零或当前节点已经是最终节点，则打印路由信息
                // 如果节点业务列表已包含当前传输的业务则终止
                // 否则继续传输
                if (dataPackage.getCounter() == 0) {
                    logger.info("传输失败，已超出生命周期:" + dataPackage);
                    continue;
                } else if (dataPackage.getPubIp() == ipService.getIpByAppName(1111l, currentName)) {
                    logger.info("传输成功: " + dataPackage);
                    continue;
                } else if (businessList.contains(businessName)){
                    logger.info("该节点已处理，该链路传输终止");
                    continue;
                } else {
                    dataPackage.decrement();
                    businessList.add(businessName);
                    node.setBusinessList(businessList);
                    List<Integer> relativeNodesList = getLink(currentName, dataPackage);
                    for (int nextNode : relativeNodesList) {
                        transferPackage(dataPackage, nextNode);
                    }
                    continue;
                }
            }

        } catch (IOException | ClassNotFoundException e) {
            e.printStackTrace();
        } finally {
            try {
                if (objectInputStream != null) {
                    objectInputStream.close();
                }
                if (inputStream != null) {
                    inputStream.close();
                }
                if (serverSocket != null) {
                    serverSocket.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }


    }

    /**
     * 根据节点名和拓扑获取当前节点连接关系
     * @param name
     * @param dataPackage
     * @return
     */
    private List<Integer> getLink(String name, DataPackage dataPackage) {
        List<Integer> relativeNodesList = new ArrayList<>();
        int[][] nodeLink = dataPackage.getNodeLink();
        int currentHop = getCurrentHop(name);
        for (int i = 0; i < nodeLink[currentHop - 1].length; i++) {
            if (i == 1) {
                relativeNodesList.add(i + 1);
            }
        }
        return relativeNodesList;
    }

    /**
     * 获取当前节点序列号
     * @param name
     * @return
     */
    private int getCurrentHop (String name) {
        if(name == null || name.length() == 0) {
            throw new RuntimeException("节点名序号错误");
        }
        return Integer.valueOf(name.substring(4, name.length()));
    }

    /**
     * 发送数据包
     * @param dataPackage
     * @param nextHop
     */
    private void transferPackage(DataPackage dataPackage, int nextHop) {
        //获取目标节点ip
        String node_name = "node" + nextHop;
        String IP = ipService.getIpByAppName(1111l, node_name);
        //发送至下一节点
        send(dataPackage, IP, 2021);
    }

    private void send(DataPackage dataPackage, String ip, int port) {
        Socket socket = null;
        try {
            socket = new Socket(ip, port);
            ObjectOutputStream objectOutputStream = new ObjectOutputStream(socket.getOutputStream());
            objectOutputStream.writeObject(dataPackage);
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                if (socket != null) {
                    socket.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

}
